package cn.mothin.frame.help;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.mothin.frame.core.base.BaseVO;
import cn.mothin.frame.core.db.SqlHelper;
import cn.mothin.frame.help.config.ConfigReader;
import cn.mothin.frame.util.StringUtil;
import cn.mothin.frame.util.encrypt.MD5File;

@SuppressWarnings("serial")
@Component("51e4d4e4d132c2b633581948")
public class AttachmentHandle implements Serializable {
	private final Log log = LogFactory.getLog(getClass());
	@Autowired
	private SqlHelper sqlHelper;

	public String makeFolder(String name) {
		Date now = new Date(System.currentTimeMillis());
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(now);

		String root = ConfigReader.getInstance().getAttachRoot() + name + "/";
		String year = String.valueOf(calendar.get(Calendar.YEAR));
		String month = String.valueOf(calendar.get(Calendar.MONTH));

		String path = year + "/" + month + "/";

		File folder = new File(root + path);
		if (!folder.exists()) {
			folder.mkdirs();
		}

		return root + path;
	}

	public String getRelativeDirectory(String path) {
		String root = ConfigReader.getInstance().getAttachRoot();
		return path.replace(root, "");
	}

	public File saveTempFile(File file, String name) {
		String path = makeFolder("temp");
		FileInputStream fileInputStream = null;
		try {
			fileInputStream = new FileInputStream(file);
			byte[] bytes = new byte[fileInputStream.available()];
			fileInputStream.read(bytes, 0, bytes.length);

			File f = new File(path + name);
			FileOutputStream fileOutputStream = null;
			try {
				fileOutputStream = new FileOutputStream(f);
				fileOutputStream.write(bytes, 0, bytes.length);
				return f;
			} catch (Exception e) {
				log.error(e);
			} finally {
				try {
					fileOutputStream.close();
				} catch (IOException e) {

				}
			}
		} catch (Exception e) {
			log.error(e);
		} finally {
			try {
				fileInputStream.close();
			} catch (IOException e) {

			}
		}
		return null;
	}

	public String save(File file) {
		FileInputStream fileInputStream = null;
		try {
			fileInputStream = new FileInputStream(file);
			byte[] bytes = new byte[fileInputStream.available()];
			fileInputStream.read(bytes, 0, bytes.length);
			return save(bytes);
		} catch (Exception e) {
			log.error(e);
		} finally {
			try {
				fileInputStream.close();
			} catch (IOException e) {

			}
		}
		return null;
	}

	public String save(byte[] bytes) {
		/*
		 * Date now = new Date(System.currentTimeMillis()); Calendar calendar =
		 * Calendar.getInstance(); calendar.setTime(now); String root =
		 * ConfigReader.getInstance().getAttachRoot(); String year =
		 * String.valueOf(calendar.get(Calendar.YEAR)); String month =
		 * String.valueOf(calendar.get(Calendar.MONTH));
		 * 
		 * String path = year + "/" + month + "/"; File folder = new File(root +
		 * path); if (!folder.exists()) { folder.mkdirs(); }
		 */
		String path = makeFolder("upload");
		path += UUID.randomUUID().toString() + ".dat";
		File f = new File(path);
		FileOutputStream fileOutputStream = null;
		try {
			fileOutputStream = new FileOutputStream(f);
			fileOutputStream.write(bytes, 0, bytes.length);
			return getRelativeDirectory(path);
		} catch (Exception e) {
			log.error(e);
		} finally {
			try {
				fileOutputStream.close();
			} catch (IOException e) {

			}
		}
		return null;
	}

	public byte[] read(String path) {
		String root = ConfigReader.getInstance().getAttachRoot();
		File file = new File(root + path);
		if (file.exists()) {
			FileInputStream fileInputStream = null;
			try {
				fileInputStream = new FileInputStream(file);
				byte[] bytes = new byte[fileInputStream.available()];
				fileInputStream.read(bytes, 0, bytes.length);
				return bytes;
			} catch (Exception e) {
				log.error(e);
			} finally {
				try {
					fileInputStream.close();
				} catch (IOException e) {

				}
			}
		}
		return null;
	}

	public byte[] readById(String id) {
		String sql = "SELECT attachmentPath FROM attachment_base WHERE id=(SELECT attachmentBaseId FROM attachment_info WHERE id=?)";
		List<String> list = sqlHelper.queryForList(String.class, sql, id);
		if (list.size() > 0) {
			return read(list.get(0));
		}
		return null;
	}

	public String queryAttachmentIds(String hostId) {
		return queryAttachmentIds(hostId, null, null);
	}

	public String queryAttachmentIds(String groupId, String documentType) {
		return queryAttachmentIds(null, groupId, documentType);
	}

	public String queryAttachmentIds(String hostId, String groupId,
			String documentType) {
		if (hostId == null && groupId == null && documentType == null) {
			return "{}";
		}
		List<Object> params = new ArrayList<Object>();
		String sql = "SELECT id FROM attachment_info WHERE TRUE ";
		if (!StringUtil.isNullOrEmpty(hostId)) {
			sql += "AND hostId=? ";
			params.add(hostId);
		}
		if (!StringUtil.isNullOrEmpty(groupId)) {
			sql += "AND groupId=? ";
			params.add(groupId);
		}
		if (!StringUtil.isNullOrEmpty(documentType)) {
			sql += "AND documentType=? ";
			params.add(documentType);
		}
		return sqlHelper.queryJson(sql, params.toArray());
	}

	public long queryAttachmentsCount(String hostId) {
		return queryAttachmentsCount(hostId, null, null);
	}

	public long queryAttachmentsCount(String groupId, String documentType) {
		return queryAttachmentsCount(null, groupId, documentType);
	}

	public long queryAttachmentsCount(String hostId, String groupId,
			String documentType) {
		if (hostId == null && groupId == null && documentType == null) {
			return -1;
		}
		List<Object> params = new ArrayList<Object>();
		String sql = "SELECT COUNT(id) FROM attachment_info WHERE TRUE ";
		if (!StringUtil.isNullOrEmpty(hostId)) {
			sql += "AND hostId=? ";
			params.add(hostId);
		}
		if (!StringUtil.isNullOrEmpty(groupId)) {
			sql += "AND groupId=? ";
			params.add(groupId);
		}
		if (!StringUtil.isNullOrEmpty(documentType)) {
			sql += "AND documentType=? ";
			params.add(documentType);
		}
		return sqlHelper.queryCount(sql, params.toArray());
	}

	public String queryAttachmentsByHostId(String hostId, boolean includeDeleted) {
		return queryAttachments(hostId, null, null, includeDeleted);
	}

	public String queryAttachmentsByGroupId(String groupId,
			String documentType, boolean includeDeleted) {
		return queryAttachments(null, groupId, documentType, includeDeleted);
	}

	public String queryAttachments(String hostId, String groupId,
			String documentType, boolean includeDeleted) {
		if (hostId == null && groupId == null && documentType == null) {
			return "";
		}
		List<Object> params = new ArrayList<Object>();
		String sql = "SELECT id,attachmentName,hostId,groupId,documentType,deleted FROM attachment_info WHERE TRUE ";
		if (!StringUtil.isNullOrEmpty(hostId)) {
			sql += "AND hostId=? ";
			params.add(hostId);
		}
		if (!StringUtil.isNullOrEmpty(groupId)) {
			sql += "AND groupId=? ";
			params.add(groupId);
		}
		if (!StringUtil.isNullOrEmpty(documentType)) {
			sql += "AND documentType=? ";
			params.add(documentType);
		}
		if (!includeDeleted) {
			sql += "AND deleted=FALSE ";
		}
		return sqlHelper.queryJson(sql, params.toArray());
	}

	public Map<String, Object> queryForDownload(String id) {
		String sql = "SELECT attachmentName,attachmentPath,attachmentType FROM attachment_info ai LEFT JOIN attachment_base ab ON ai.attachmentBaseId=ab.id WHERE ai.id=?";
		return sqlHelper.queryForMap(sql, id);
	}

	/**
	 * 获取附件类型
	 * 
	 * @param id
	 *            附件Id
	 * @return
	 */
	public String queryAttachmentType(String id) {
		String sql = "SELECT attachmentType FROM attachment_info ai LEFT JOIN attachment_base ab ON ai.attachmentBaseId=ab.id WHERE ai.id=?";
		List<String> list = sqlHelper.queryForList(String.class, sql, id);
		if (list.size() > 0) {
			return list.get(0);
		}
		return null;
	}

	public String add(String hostId, String memo, String uploadBy, File upload,
			String uploadFileName, String uploadContentType) {
		return add(hostId, null, null, memo, uploadBy, upload, uploadFileName,
				uploadContentType);
	}

	public String add(String groupId, String documentType, String memo,
			String uploadBy, File upload, String uploadFileName,
			String uploadContentType) {
		return add(null, groupId, documentType, memo, uploadBy, upload,
				uploadFileName, uploadContentType);
	}

	public String add(String hostId, String groupId, String documentType,
			String memo, String uploadBy, File upload, String uploadFileName,
			String uploadContentType) {
		String id = UniqueCode.make();
		String fileMD5 = null;
		Date now = new Date(System.currentTimeMillis());
		try {
			fileMD5 = MD5File.getFileMD5String(upload);
		} catch (IOException e) {
			log.error(e);
			return null;
		}
		save(upload, fileMD5, uploadContentType);
		String sql = "INSERT INTO attachment_info(id,attachmentBaseId,attachmentName,hostId,groupId,documentType,uploadBy,uploadTime,memo,deleted) VALUES(?,?,?,?,?,?,?,?,?,false)";
		sqlHelper.execute(sql, id, fileMD5, uploadFileName, hostId, groupId,
				documentType, uploadBy, now, memo);

		sql = "INSERT INTO convert_queue(id,inTime,state) VALUES(?,?,?)";
		sqlHelper.execute(sql, id, now, 0);
		return id;
	}

	public int add(String hostId, String memo, String uploadBy, File[] uploads,
			String[] uploadsFileName, String[] uploadsContentType) {
		return add(hostId, null, memo, uploadBy, uploads, uploadsFileName,
				uploadsContentType);
	}

	public int add(String groupId, String documentType, String memo,
			String uploadBy, File[] uploads, String[] uploadsFileName,
			String[] uploadsContentType) {
		return add(null, groupId, documentType, memo, uploadBy, uploads,
				uploadsFileName, uploadsContentType);
	}

	public int add(String hostId, String groupId, String documentType,
			String memo, String uploadBy, File[] uploads,
			String[] uploadsFileName, String[] uploadsContentType) {
		if (uploads != null && uploads.length > 0) {
			for (int i = 0; i < uploads.length; i++) {
				String id = add(hostId, groupId, documentType, memo, uploadBy,
						uploads[i], uploadsFileName[i], uploadsContentType[i]);
				if (id == null) {
					return 2;
				}
			}
			return 0;
		}
		return 1;
	}

	public int add(String hostId, String memo, String uploadBy, BaseVO form) {
		return add(hostId, null, memo, uploadBy, form.getUploads(),
				form.getUploadsFileName(), form.getUploadsContentType());
	}

	public int add(String groupId, String documentType, String memo,
			String uploadBy, BaseVO form) {
		return add(null, groupId, documentType, memo, uploadBy,
				form.getUploads(), form.getUploadsFileName(),
				form.getUploadsContentType());
	}

	public int add(String hostId, String groupId, String documentType,
			String memo, String uploadBy, BaseVO form) {
		return add(hostId, groupId, documentType, memo, uploadBy,
				form.getUploads(), form.getUploadsFileName(),
				form.getUploadsContentType());
	}

	/**
	 * 删除指定的附件
	 * 
	 * @param id
	 *            附件Id
	 * @param deletedBy
	 *            删除者Id
	 */
	public void deleteAttachment(String id, String deletedBy) {
		String sql = "UPDATE attachment_info SET deletedBy=? ,deletedTime=?,deleted=TRUE WHERE id=?";
		sqlHelper.execute(sql, deletedBy, new Date(System.currentTimeMillis()),
				id);
	}

	/**
	 * 保存附件文件
	 * 
	 * @param file
	 *            文件
	 * @param md5
	 *            散列值
	 * @param contentType
	 *            文件类型
	 */
	private void save(File file, String md5, String contentType) {
		String sql = "SELECT COUNT(1) FROM attachment_base WHERE id=?";
		long count = sqlHelper.queryCount(sql, md5);
		if (count == 0) {
			String path = save(file);
			sql = "INSERT INTO attachment_base(id,attachmentPath,attachmentSize,attachmentType) VALUES(?,?,?,?)";
			sqlHelper.execute(sql, md5, path, file.length(), contentType);
		}
	}

	public void setAttachmentState(String id, boolean deleted, String deletedBy) {
		String sql = null;
		if (deleted) {
			sql = "UPDATE attachment_info SET deleted=TRUE ,deletedBy=?,deletedTime=? WHERE id=?";
			sqlHelper.execute(sql, deletedBy,
					new Date(System.currentTimeMillis()), id);
		} else {
			sql = "UPDATE attachment_info SET deleted=FALSE ,deletedBy=NULL,deletedTime=NULL WHERE id=?";
			sqlHelper.execute(sql, id);
		}
	}
}
